import tkinter as tk
import pyaudio
import wave
import threading
import tkinter.messagebox
import os
import cv2
from PIL import Image,ImageTk
import mediapipe as mp #媒体管道
import time


class MainPage:
    def __init__(self,master:tk.Tk):
        self.cap = cv2.VideoCapture(0)
        self.mpDraw = mp.solutions.drawing_utils #预先声明函数
        self.mpPose = mp.solutions.pose #点姿势方案
        self.pose = self.mpPose.Pose()  #物体姿势


        with open('cn_chapter.txt',mode='r',encoding='utf-8') as f:
            self.TextRead = f.read()

    
        self.root = master
        self.root.geometry('1800x1200')
        self.root.title('魔镜 V0.0.1')
        self.page = tk.Frame(self.root)
        self.page.pack()

        self.panel = tk.Label(self.page)  #对Label下定义， 初始化图像管道
        self.panel.pack(padx=10, pady=10)
        self.root.config(cursor="arrow")

        self.text = tk.Text(self.page, width=60, height=10,autoseparators=True)
        self.text.pack(pady=30)#每行的宽度为60，显示8行#竖直边距设为30
        self.text.insert(tk.INSERT,self.TextRead)
        self.text.tag_add('tag1','0.0')
        self.text.tag_config('tag1',lmargin1=20)
        
        tk.Button(self.page,text='开始录制',command=self.start).pack(side='left',padx=10)
        tk.Button(self.page,text='停止录制',command=self.stop).pack(side='left',padx=10)
        tk.Button(self.page,text='重新录制',command=self.restart).pack(side='left',padx=10)
        tk.Button(self.page,text='  确认  ',command=self.sure).pack(side='left',padx=10)
        self.lbStatus = tk.Label(self.page, text='Ready', anchor='w', fg='green')    #靠左显示绿色状态字
        self.lbStatus.place(x=250, y=350, width=200, height=20)
        
         #音频采样率
        self.fileName = 'cn_chapter.wav' #文件名
        self.allowRecording = False      #录音状态
        self.CHUNK_SIZE = 1024           #数据块大小
        self.CHANNELS = 1                #频道
        self.FORMAT = pyaudio.paInt16    #16位量化编码
        self.RATE = 16000                #44100采样率


    def record(self):
        p = pyaudio.PyAudio()
        #audio流对象
        stream = p.open(format=self.FORMAT,
                        channels=self.CHANNELS,
                        rate=self.RATE,
                        input=True,
                        frames_per_buffer=self.CHUNK_SIZE)
        
        if os.path.exists("cn_chapter.wav"):    #判断是否存在对应文件
            os.remove("cn_chapter.wav")         #删除以实现覆盖写人
        
        #音频文件对象
        wf = wave.open(self.fileName, 'wb')
        wf.setnchannels(self.CHANNELS)
        wf.setsampwidth(p.get_sample_size(self.FORMAT))
        wf.setframerate(self.RATE)

        # 读取数据写入文件
        while self.allowRecording:
            data = stream.read(self.CHUNK_SIZE)
            wf.writeframes(data)
        wf.close()
        stream.stop_stream()
        stream.close()
        p.terminate()
        self.fileName = None

    def video_loop(self):
        
        pTime = time.time()

        while True:
            success, img = self.cap.read()
            # 转化图像
            imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) #转化为RGB，opencv用的是RGB格式的图片
            results = self.pose.process(imgRGB) #将转化图片赋值
            # print(results.pose_landmarks) #打印实际的地标参数值，xyz
            if results.pose_landmarks:
                self.mpDraw.draw_landmarks(img, results.pose_landmarks, self.mpPose.POSE_CONNECTIONS) #点画地标 画下划线地标
                # 枚举 id 和 地标
                for id, lm in enumerate(results.pose_landmarks.landmark):
                    h, w, c = img.shape
                    #print(id, lm) #显示33个点的坐标的信息
                    cx, cy = int(lm.x * w), int(lm.y * h) #cx，cy分别为对应的点的像素坐标位置
                    cv2.circle(img, (cx, cy), 5, (255, 0, 0), cv2.FILLED) #改变对应圆圈，大小、颜色填充度等

            # 制作帧率显示
            cTime = time.time()
            fps = 1/(cTime-pTime)
            #fps = cTime-pTime
            pTime = cTime
            # 显示帧率，第二个为数值，第三个参数是位置，文字样式，文字大小,颜色，粗度
            cv2.putText(img, str(int(fps)), (70,50),cv2.FONT_HERSHEY_PLAIN, 3,(255,0,0),3)
            
            
            cv2image = cv2.cvtColor(img, cv2.COLOR_BGR2RGBA)
            current_image = Image.fromarray(cv2image)        # 将图像转换成Image对象
            imgtk = ImageTk.PhotoImage(image=current_image)
            self.panel.config(image=imgtk)# 图像显示    
            root.after(50,self.video_loop)## 延时50毫秒，再次调用本函数
            root.mainloop()# gui线程里要尽快执行完工作返回消息机制里，如果把这句写在函数外面，则图像不会显示


            #cv2.imshow("Image", img)
            #cv2.waitKey(1) #每秒100帧，减小他可以设置为10


        
    def start(self):
        self.allowRecording = True
        self.lbStatus['text'] = 'Recording...'
        threading.Thread(target=self.record).start()
        self.video_loop()
     

    def stop(self):
        self.allowRecording = False
        self.lbStatus['text'] = 'Ready'
        self.cap.release()
    
    def restart(self):
        self.stop()
        self.start()

    def sure(self):
        from JScore import JScore
        self.page.destroy()
        JScore().show(master=self.root)
        
    def closeWindow(self):
        if self.allowRecording:
            tkinter.messagebox.showerror('Recording', 'Please stop recording before close the window.')
            return
        root.destroy()

    
if __name__ == '__main__':
    root = tk.Tk()
    MP=MainPage(root)
    root.protocol('WM_DELETE_WINDOW', MP.closeWindow)
    root.mainloop()
